
`define SIZE_BYTE 3'b00
`define SIZE_HALF 3'b01
`define SIZE_WORD 3'b10
`define SM2_Reg_addr SM2_ofs_addr[11:5]			//register offset address
`define X_N SM2_ofs_addr[4:2]					//Number
`define SM2_Reg_addr_R  HADDR[11:5]			//register offset address
`define X_N_R           HADDR[4:2]					//Number

module top_SM2(
input HRESETn,HCLK,HWRITE,HSEL,HMASTLOOK,
input [1:0] HTRANS,
input [2:0] HSIZE,HBURST,
input [31:0] HADDR,HWDATA,
input [3:0] HPROT,
output HREADY,HRESP,
output [31:0] HRDATA,
output sm2_vic_int
);


parameter
	SM2_base_addr=32'h50001xxx,
	addr_x1=7'h0,addr_x2=7'h1,addr_y1=7'h2,addr_y2=7'h3,addr_k=7'h4,addr_x3=7'h5,addr_y3=7'h6,
	addr_control=12'h0e0,addr_status=12'h0e4;


reg [31:0] x1 [0:7]	;						//Define 8 word 32 bit register ,save x1
reg [31:0] x2 [0:7]	;						//Define 8 word 32 bit register ,save x2
reg [31:0] y1 [0:7]	;						//Define 8 word 32 bit register ,save y1
reg [31:0] y2 [0:7]	;						//Define 8 word 32 bit register ,save y2
reg [31:0] k  [0:7]	;						//Define 8 word 32 bit register ,save k
reg [31:0] control_reg;						//control register
reg [31:0] x3 [0:7]	;						//Define 8 word 32 bit register ,save x3
reg [31:0] y3 [0:7]	;						//Define 8 word 32 bit register ,save y3
wire [31:0] x3_1,x3_2,x3_3,x3_4,x3_5,x3_6,x3_7,x3_8;
wire [31:0] y3_1,y3_2,y3_3,y3_4,y3_5,y3_6,y3_7,y3_8;
always @(x3_1 or x3_2 or x3_3 or x3_4 or x3_5 or x3_6 or x3_7 or x3_8) begin
{x3[7],x3[6],x3[5],x3[4],x3[3],x3[2],x3[1],x3[0]} = {x3_1,x3_2,x3_3,x3_4,x3_5,x3_6,x3_7,x3_8};
end

always @(y3_1 or y3_2 or y3_3 or y3_4 or y3_5 or y3_6 or y3_7 or y3_8) begin
{y3[7],y3[6],y3[5],y3[4],y3[3],y3[2],y3[1],y3[0]} = {y3_1,y3_2,y3_3,y3_4,y3_5,y3_6,y3_7,y3_8};
end
wire [31:0] status_reg;
//wire  sm2_vic_int;
    wire ahb_trans_valid;
    wire ahb_trans_clear;
    wire ahb_write_en;
    wire ahb_read_en;
    reg lite_write_req;
    reg lite_read_req;

reg [31:0] 	rdata;

reg [1:0] 	HTRANS_reg;
reg 		HWRITE_reg,HSEL_reg;
reg [11:0] Reg_ofs_addr_ff;
wire [11:0] SM2_ofs_addr;
reg [2:0]  HSIZE_reg;

assign HRDATA=rdata;
assign HREADY= 1'b1;
assign HRESP=  1'b0;

    assign ahb_trans_valid = HSEL && HREADY && 
                             (HTRANS[1] == 1'b1);
    assign ahb_write_en = ahb_trans_valid && HWRITE;
    assign ahb_read_en  = ahb_trans_valid && (!HWRITE);
//    assign ahb_trans_clear = hready && !hsel;
    //////////////////////////Write enable signal///////////////////////////////
    always @ (posedge HCLK or negedge HRESETn)
    begin
      if(!HRESETn)
      begin
        lite_write_req <= 1'b0;
      end
      else if (ahb_write_en)
      begin
        lite_write_req <= 1'b1;
      end
      else
      begin
        lite_write_req <= 1'b0;
      end 
    end
////////////////ADDR,TRANS,WRITE signal input//////////////////////
    always@(posedge HCLK or negedge HRESETn)
      begin 
        if(!HRESETn)
          begin 
            Reg_ofs_addr_ff  <=    12'hfff;
            HSIZE_reg   <=  3'b0;
          end
        else if(ahb_trans_valid)
          begin  
            Reg_ofs_addr_ff  <=    HADDR[11:0];
            HSIZE_reg   <=  HSIZE;
          end
        else
          begin  
            Reg_ofs_addr_ff  <=    12'hfff;
            HSIZE_reg   <=   3'b0;
          end        
      end

  assign   SM2_ofs_addr = Reg_ofs_addr_ff;
//////////////////////control_reg input//////////////////////////////////
    always@(posedge HCLK or negedge HRESETn)  
      begin  
        if( !HRESETn)
            control_reg    <=    32'hffff_ffff;
        else if( (SM2_ofs_addr==addr_control)&&(lite_write_req == 1'b1)&&(HSIZE_reg == `SIZE_WORD) )
            control_reg    <=    HWDATA;
//	else if( (status_reg[3:0] == 4'h2)&&(`SM2_Reg_addr==addr_x3)&&(!HWRITE_reg)&&(HTRANS_reg[1])&&(HSEL_reg)&&(HSIZE_reg == `SIZE_WORD) )		//Compute finish and read X3
//		control_reg[4] <=	1;	//???
        else
            control_reg	<= control_reg;
  end  
  
//////////////////////HWDATA input//////////////////////////////////////// 
integer sm2_i;
always@(posedge HCLK or negedge HRESETn)
begin
	if(!HRESETn) begin
		for(sm2_i = 0; sm2_i<8; sm2_i=sm2_i+1)begin
			x1[sm2_i] <=	32'h0;	y1[sm2_i] <=	32'h0;	x2[sm2_i] <=	32'h0;	y2[sm2_i] <=	32'h0;	k[sm2_i] <=	32'h0;
		end
	end
	else if(control_reg[5]==1'b1)begin
        for(sm2_i = 0; sm2_i<8; sm2_i=sm2_i+1)begin
            x1[sm2_i] <=    32'h0;    y1[sm2_i] <=    32'h0;    x2[sm2_i] <=    32'h0;    y2[sm2_i] <=    32'h0;    k[sm2_i] <=    32'h0;
        end
	end
	else if( (lite_write_req == 1'b1)&&(HSIZE_reg == `SIZE_WORD) )begin
		case(`SM2_Reg_addr)
			addr_x1:	x1[`X_N] <=	HWDATA;
			addr_y1:	y1[`X_N] <=	HWDATA;
			addr_x2:	x2[`X_N] <=	HWDATA;
			addr_y2:	y2[`X_N] <=	HWDATA;
			addr_k :	k[`X_N]  <=	HWDATA;
	//		default:
		endcase
	end
	else 
		for(sm2_i = 0; sm2_i<8; sm2_i=sm2_i+1)begin
			x1[sm2_i] <=x1[sm2_i];	y1[sm2_i] <=y1[sm2_i];	x2[sm2_i] <=x2[sm2_i];	y2[sm2_i] <=y2[sm2_i];	k[sm2_i] <=k[sm2_i];
		end
end

//////////////////////HRDATA output//////////////////////////////////////// 
always@(posedge HCLK or negedge HRESETn)
  begin
    if(!HRESETn)begin
        rdata<=32'hFFFF_FFFF;
    end
    else if( ahb_read_en && (HSIZE == `SIZE_WORD) )
	case(`SM2_Reg_addr_R)
		addr_x1:	rdata <= x1[`X_N_R];
		addr_y1:	rdata <= y1[`X_N_R];
		addr_x2:	rdata <= x2[`X_N_R];
		addr_y2:	rdata <= y2[`X_N_R];
		addr_k :		rdata <=  k[`X_N_R];
		addr_x3:	rdata <= x3[`X_N_R];
		addr_y3:	rdata <= y3[`X_N_R];
		default:begin
			if(HADDR[11:0] == addr_status)			//CPU read status_reg
				rdata <= status_reg;
			else if(HADDR[11:0] == addr_control)
				rdata <= control_reg;
			else                             //Read invalid address,return 0xffff_ffff(-1) 
				rdata<=32'hFFFF_FFFF;
		end
	endcase
	else
	   	rdata <= rdata;	  	 
  end

ECC256 ECC256_inst1(
.rst_n(HRESETn),.clk(HCLK),.mode_sm2(control_reg),
.x1_1(x1[7]),.x1_2(x1[6]),.x1_3(x1[5]),.x1_4(x1[4]),.x1_5(x1[3]),.x1_6(x1[2]),.x1_7(x1[1]),.x1_8(x1[0]),
.x2_1(x2[7]),.x2_2(x2[6]),.x2_3(x2[5]),.x2_4(x2[4]),.x2_5(x2[3]),.x2_6(x2[2]),.x2_7(x2[1]),.x2_8(x2[0]),
.y1_1(y1[7]),.y1_2(y1[6]),.y1_3(y1[5]),.y1_4(y1[4]),.y1_5(y1[3]),.y1_6(y1[2]),.y1_7(y1[1]),.y1_8(y1[0]),
.y2_1(y2[7]),.y2_2(y2[6]),.y2_3(y2[5]),.y2_4(y2[4]),.y2_5(y2[3]),.y2_6(y2[2]),.y2_7(y2[1]),.y2_8(y2[0]),
.k_1(k[7]),.k_2(k[6]),.k_3(k[5]),.k_4(k[4]),.k_5(k[3]),.k_6(k[2]),.k_7(k[1]),.k_8(k[0]),
.state_sm2(status_reg),
.x3_1(x3_1),.x3_2(x3_2),.x3_3(x3_3),.x3_4(x3_4),.x3_5(x3_5),.x3_6(x3_6),.x3_7(x3_7),.x3_8(x3_8),
.y3_1(y3_1),.y3_2(y3_2),.y3_3(y3_3),.y3_4(y3_4),.y3_5(y3_5),.y3_6(y3_6),.y3_7(y3_7),.y3_8(y3_8),
.sm2_vic_int(sm2_vic_int)
);



`ifdef SM2_sim
reg[255:0] data_x;
reg[255:0] data_y;

//sim
always@(x3) begin
data_x={x3[0],x3[1],x3[2],x3[3],x3[4],x3[5],x3[6],x3[7]};
end

always@(y3) begin
data_y={y3[0],y3[1],y3[2],y3[3],y3[4],y3[5],y3[6],y3[7]};
end

always@(status_reg)
begin 
     if((status_reg==32'h2))
     begin
     $display("data_x:%h",data_x);
     $display("data_y:%h",data_y);
     $display("Time:%t",$time);
     end
     else
     $display("testing_sm2");
end
`else


`endif


  
endmodule
